import json
from flask import request

from flask_limiter.util import get_remote_address
from flask_restful import Resource, current_app  # current_app 上下文
from random import randint
# 加载数据库的配置
from comment.models import db
from comment.models.user import User
# 阿里云的短信服务
from comment.utils.deactors import login_required
from comment.utils.demo_sms_send import send_sms
from comment.utils.parse_yanzheng import mobile, code_mobile, email_
from comment.utils.shopping_redis import redis_client
from comment.utils.token_pyjwt import generate
from shopping.resources.user import constans
from flask_restful import reqparse
from comment.utils.limiter import limiter as lmt


# 创建一个资源 测试日志是否可以正常运行
class Shopping_user(Resource):
    # 进行登录拦截测试 需要先进行登录，然后才能访问到get里面的内容
    method_decorators = {
        'get': [login_required],
        'post': [login_required]
    }

    def get(self):
        # 测试日志是否可以正常运行
        # debug，设置日志级别为debug
        current_app.logger.debug('哈哈哈')
        print('--->', current_app.logger)
        return {'hello': '测试'}

    def post(self):
        return {'post': 'post'}

    def put(self):
        return {'put': 'pl'}


# 创建一个资源，用来发送短信
class Send_SMS(Resource):
    # 创建多个限流器
    error_message = '验证码发送次数过多，请稍后再试'
    decorators = [
        # 参数1：限流的速率，参数二:调用的函数,参数三：超出规定限制的错误信息
        lmt.limit(constans.LIMIT_SMS_CODE_BY_MOBILE, key_func=lambda: request.args['phone'],
                  error_message=error_message),
        lmt.limit(constans.LIMIT_SMS_CODE_BY_IP, key_func=get_remote_address, error_message=error_message)
    ]

    def get(self):
        phone = request.args.get('phone')
        code = randint(100000, 999999)  # 随机生成6位数的验证码
        result = send_sms(phone, str(code))
        # print(result)
        # 将json变为字典
        result = json.loads(result)
        # 将获取到的手机号传给redis
        result['phone'] = phone
        print('------>', result['phone'])
        # 验证码发送成功后，将缓存数据和短信验证码存储到redis数据库中  规定时间为5分钟
        # 参数1：发送的手机号  参数二： 验证码的有效时间  参数三： 验证码
        redis_client.setex(f'shopping:code:{phone}', constans.SMS_CODE_EXEPIREX, code)
        return result


class AuthorRlationCode(Resource):
    """
    创建一个资源，用来进行手机验证码的验证
    使用正则表达式
    """

    def post(self):
        # 创建一个验证对象
        rq = reqparse.RequestParser()
        # 添加参数
        rq.add_argument('phone', type=mobile, required=True)
        rq.add_argument('code', type=code_mobile(r'^\d{6}$'), required=True)
        args = rq.args()
        # 取出code 和 phone
        phone = args.phone
        code = args.cdoe

        # 从redis中取出保存的验证码
        # 获取redis中的存储验证码的键
        key = f'shopping:code:{phone}'
        try:
            # 拿出验证码
            code_ = redis_client.get(key)
        # redis出现连接错误
        except ConnectionError as e:
            current_app.logger.error(e)
            return {"message": "redis connect error"}, 400
        # 如果填写的验证码和取出的验证码不一致
        if not code_ or code_.decode() != code:
            return {"message": "code is error"}, 400
        # 验证通过
        return {"phone": phone, 'code': code, 'message': '验证通过'}


class RegiseterResource(Resource):
    """
    注册验证
    """

    def post(self):
        rq = reqparse.RequestParser()
        # 添加参数
        rq.add_argument('phone', type=mobile, required=True)
        rq.add_argument('username', required=True)
        rq.add_argument('password', required=True)
        rq.add_argument('email', type=email_, required=True)

        # 获取参数
        arg = rq.parse_args()
        phone = arg.phone
        username = arg.username
        password = arg.password
        email = arg.email

        # 判断用户名是否唯一
        u = User.query.filter(User.username == username).first()  # User 1
        if u:
            current_app.logger.info(f'{username}已经存在')
            return {'message': f'{username} is alread exists'}
        else:
            # 需要对密码进行加密 使用flask中提供得模块
            # 将信息添加到数据库中
            user = User()
            user.phone = phone
            user.username = username
            user.pwd = password
            user.email = email
            user.status = 0  # 0：状态正常
            db.session.add(user)
            db.session.commit()
            return {'message': 'ok'}


class Login(Resource):
    """
    登录
    """

    def post(self):
        rq = reqparse.RequestParser()
        rq.add_argument('username', required=True)
        rq.add_argument('password', required=True)
        arf = rq.parse_args()
        username = arf.username
        password = arf.password

        # 判断密码或者用户名是否正确
        u = User.query.filter(User.username == username).first()  # user1
        if not u:
            return {'message': f'{username} not exists'}
        if u:
            # 检查用户密码是否正确
            if u.check_password(password):
                # 在登录成功后，使用用户id生成token,并且返回给前端
                token = generate(u.id)
                return {'message': 'Login Success', 'token': token}
            else:
                return {'message': 'username or password error'}
